//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.rewa.test.config;

import com.alibaba.druid.util.StringUtils;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
import springfox.documentation.service.SecurityReference;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.List;

/**
 * @author tanfangping
 */
@Configuration
@ConditionalOnProperty(
        value = {"swagger.enabled"},
        matchIfMissing = true
)
@EnableConfigurationProperties({SwaggerProperties.class})
@EnableSwagger2
@Slf4j
@NoArgsConstructor
public class SwaggerAutoConfig {

    @Autowired
    private SwaggerProperties swaggerProperties;

    @Bean
    public Docket createRestApi() {
        ApiInfo api = (new ApiInfoBuilder()).title(this.swaggerProperties.getTitle()).description(this.swaggerProperties.getDescription()).version(this.swaggerProperties.getVersion()).build();
        if (this.swaggerProperties.isEnable()) {
            if (StringUtils.isEmpty(this.swaggerProperties.getBasePackage())) {
                log.error("未设置Swagger扫描基础包");
                return null;
            }

            log.info("当前服务已启用Swagger在线API文档，扫描注解[@RestController]，扫描基础包：[{}]", this.swaggerProperties.getBasePackage());
            Docket docket = (new Docket(DocumentationType.SWAGGER_2)).apiInfo(api).select().apis(RequestHandlerSelectors.withClassAnnotation(RestController.class)).apis(RequestHandlerSelectors.basePackage(this.swaggerProperties.getBasePackage())).paths(PathSelectors.any()).build();
            // 设置全局通用参数
//            this.setGlobalOperationParameters(docket);
            this.setSecuritySchemes(docket);
            this.setSecurityContexts(docket);
            return docket;
        } else {
            log.info("当前项目已禁用Swagger");
            return (new Docket(DocumentationType.SWAGGER_2)).apiInfo(api).select().paths(PathSelectors.none()).build();
        }
    }

    private void setSecuritySchemes(Docket docket) {
        if (!this.swaggerProperties.isAuthable()) {
            log.warn("当前服务关闭了Swagger全局安全权限,忽略");
        } else {
            log.debug("开始执行[设置Swagger全局安全权限]");
            ApiKey authApiKey = new ApiKey("Authorization", this.swaggerProperties.getAuthHeadParaName(), "header");
            List<ApiKey> apiKeys = new ArrayList();
            apiKeys.add(authApiKey);
            log.debug("设置Swagger全局安全参数名为[{}]", authApiKey.getKeyname());
            docket.securitySchemes(apiKeys);
            log.debug("完成执行[设置Swagger全局安全权限]");
        }
    }

    private void setSecurityContexts(Docket docket) {
        log.debug("开始执行[设置Swagger安全Context]");
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[]{authorizationScope};
        List<SecurityReference> securityReferences = new ArrayList();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        List<SecurityContext> rs = new ArrayList();
        // 所有包含"auth"的接口不需要使用securitySchemes,即不认证
        rs.add(SecurityContext.builder().securityReferences(securityReferences).forPaths(PathSelectors.regex("^(?!auth).*$")).build());
        docket.securityContexts(rs);
        log.debug("完成执行[设置Swagger安全Context]");
    }

//    private void setGlobalOperationParameters(Docket docket) {
//        log.debug("开始执行[设置Swagger接口共通参数]处理");
//        List<Parameter> paras = new ArrayList();
//        paras.add((new ParameterBuilder()).name("tenantId").description("租户ID").modelRef(new ModelRef("String")).parameterType("header").required(false).defaultValue("").order(1).build());
//        paras.add((new ParameterBuilder()).name("operatorId").description("用户ID").modelRef(new ModelRef("String")).parameterType("header").required(false).defaultValue("").order(2).build());
//        paras.add((new ParameterBuilder()).name("trackId").description("跟踪ID").modelRef(new ModelRef("String")).parameterType("header").required(false).defaultValue("").order(3).build());
//        paras.add((new ParameterBuilder()).name("client").description("应用ID").modelRef(new ModelRef("String")).parameterType("header").required(false).defaultValue("").order(4).build());
//        paras.add((new ParameterBuilder()).name("uiName").description("客户端UI名称").modelRef(new ModelRef("String")).parameterType("header").required(false).defaultValue("").order(5).build());
//        docket.globalOperationParameters(paras);
//        log.debug("完成执行[设置Swagger接口共通参数]处理，Swagger接口共通参数：[{}]", paras);
//    }

}
